package main

import (
	"errors"
	"fmt"
	"log"
	"math"
	"os"
	"regexp"
	"strconv"
	"strings"

	"github.com/wargarblgarbl/libgosubs/srt"
)

const VIDEO_FILE = "video.mp4"
const SUBTITLE_FILE = "video.srt"
const OUT_SUBTITLE_FILE = "new-video.srt"
const OUT_VIDEO_FILE = "new-video.mp4"
const CMD_FILE = "第五步-根据字幕剪视频.bat"

func main() {
	if _, err := os.Stat(VIDEO_FILE); errors.Is(err, os.ErrNotExist) {
		fmt.Errorf("file %s not exists", VIDEO_FILE)
		return
	}
	if _, err := os.Stat(SUBTITLE_FILE); errors.Is(err, os.ErrNotExist) {
		fmt.Errorf("file %s not exists", SUBTITLE_FILE)
		return
	}

	subRip, _err := srt.ParseSrt(SUBTITLE_FILE)
	if _err != nil {
		panic(_err)
	}
	var subTitles []srt.Subtitle
	var btArr []string
	var timeMinus float64
	var cId int = 0
	var prevMns bool
	var startPos float64
	var lastEndf float64
	var grepMode bool = len(os.Args) > 1
	for _, c := range subRip.Subtitle.Content {
		var hit bool
		if grepMode {
			hit = !strings.HasPrefix(c.Line[0], "==")
		} else {
			hit = strings.HasPrefix(c.Line[0], "==")
		}
		if hit {
			/*
				tbpos, terr := timeStr2float(c.Start)
				if terr != nil {
					panic(terr)
				}
			*/

			if !prevMns && lastEndf > 0 {
				btArr = append(btArr, fmt.Sprintf("between(t,%.2f,%.2f)", startPos, lastEndf))
				prevMns = true
			}

			tepos, terr := timeStr2float(c.End)
			if terr != nil {
				panic(terr)
			}
			startPos = tepos
			timeMinus += tepos - lastEndf
			lastEndf = tepos
		} else {
			// tbpos, terr := timeStr2float(c.Start)
			// if terr != nil {
			// 	panic(terr)
			// }

			cId += 1
			dst, det, _, epos, _err := strTimeMinus(c.Start, c.End, timeMinus)
			if _err != nil {
				panic(_err)
			}

			if grepMode {
				c.Line[0] = strings.ReplaceAll(c.Line[0], "==", "")
			}

			subTitles = append(subTitles, srt.Subtitle{
				Id:    cId,
				Start: dst,
				End:   det,
				Line:  c.Line,
			})

			lastEndf = epos
			if prevMns {
				prevMns = false
			}
		}
	}

	if !prevMns && lastEndf > 0 {
		btArr = append(btArr, fmt.Sprintf("between(t,%.2f,%.2f)", startPos, lastEndf))
	}

	var subt struct {
		Content []srt.Subtitle
	}
	subt.Content = subTitles
	srt.WriteSrt(&srt.SubRip{subt}, OUT_SUBTITLE_FILE)

	mergBtw := strings.Join(btArr, "+")

	ffmpegCmd := fmt.Sprintf(`ffmpeg -y -i %s -vf "select='%s', setpts=N/FRAME_RATE/TB" -af "aselect='%s',asetpts=N/SR/TB" %s`, VIDEO_FILE, mergBtw, mergBtw, OUT_VIDEO_FILE)

	f, err := os.OpenFile(CMD_FILE, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0755)
	if err != nil {
		log.Fatal(err)
	}
	f.WriteString(ffmpegCmd)
	fmt.Println("finish")
}

//timeStr2float 把字符时间转成浮点数时间
func timeStr2float(tstr string) (tflot float64, err error) {
	params := regexp.MustCompile(`^(\d+):(\d+):(\d+),(\d+)$`).FindStringSubmatch(tstr)
	if len(params) == 5 {
		var v1, v2, v3, v4 float64
		v1, err = strconv.ParseFloat(params[1], 64)
		if err != nil {
			return
		}
		v2, err = strconv.ParseFloat(params[2], 64)
		if err != nil {
			return
		}
		v3, err = strconv.ParseFloat(params[3], 64)
		if err != nil {
			return
		}
		v4, err = strconv.ParseFloat(params[4], 64)
		if err != nil {
			return
		}

		tflot = (v1 * 3600) + (v2 * 60) + v3 + (v4 / 1000)
	} else {
		err = errors.New("can not parse time string")
	}
	return
}

func float2timestr(fv float64) (str string, err error) {
	var delta float64 = fv
	var h, m, s, ss int64
	if delta >= 3600 {
		h = int64(delta / 3600)
		delta = math.Mod(delta, 3600)
	}
	if delta >= 60 {
		m = int64(delta / 60)
		delta = math.Mod(delta, 60)
	}
	iv, fv := math.Modf(delta)
	s = int64(iv)
	ss = int64(fv * 1000)
	str = fmt.Sprintf("%02d:%02d:%02d,%03d", h, m, s, ss)
	return
}

func strTimeMinus(str1, str2 string, dalta float64) (ret1, ret2 string, sval1, sval2 float64, err error) {
	sval1, err = timeStr2float(str1)
	if err != nil {
		return
	}

	tval1 := sval1 - dalta

	ret1, err = float2timestr(tval1)

	sval2, err = timeStr2float(str2)
	if err != nil {
		return
	}

	tval2 := sval2 - dalta

	ret2, err = float2timestr(tval2)
	return
}
